home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / 3DDEMO.ZIP / 3D / SOURCE / VIDEO.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-22  |  16.4 KB  |  601 lines

  1. #include "video.hpp"
  2.  
  3. // Copyright (c) 1996 by Kerrigan Burgess, all rights reserved.
  4.  
  5. unsigned char *LookPal;           // Linear palette
  6. unsigned char *LookPalPhong;      // Phong palette (phong illumination model)
  7.  
  8. unsigned char *TransTBL;
  9. unsigned char *HazeTBL;
  10. int           *PhongTBL;          // holds angles.
  11. int           *TextureMap;
  12.  
  13. int   SCREENWIDTH;
  14. int   SCREENHEIGHT;
  15. int   SCREENSIZE;
  16. int   HALF_SCREEN_WIDTH;
  17. int   HALF_SCREEN_HEIGHT;
  18. int   ASPECT_SCREEN_HEIGHT;
  19. int   YON_Z;
  20. int   HITHER_Z;
  21.  
  22. float HALF_SCREEN_WIDTH_VD;
  23. float HALF_SCREEN_HEIGHT_VD;
  24. float SCANLINELENGTH;
  25.  
  26. int GetMode(void);
  27. #pragma aux GetMode =\
  28.     "mov ah,0x0F",\
  29.     "int 0x10,"\
  30.     "and eax,0xFF",\
  31.  
  32. int SetMode(int);
  33. #pragma aux SetMode =\
  34.     "int 0x10",\
  35.     parm [eax]\
  36.  
  37. void ZapBuff(unsigned char *Dest,unsigned char *Source,int Count);
  38. #pragma aux ZapBuff =\
  39.      "rep movsd"\
  40.      modify [edi esi ecx]\
  41.      parm [edi] [esi] [ecx]\
  42.      ;
  43.      
  44. VIDEOCLASS::VIDEOCLASS(void)                 // Constructor
  45. {
  46.    VidMem=(unsigned char *)0xa0000;   // pointer to VidMem.
  47.    pcx = new PcxFile;
  48.    memset (pcx,'\0',sizeof(PcxFile));     // clear
  49.  
  50.    Background=NULL;
  51.    VideoBuffer=NULL;
  52.    TransTBL=NULL;
  53.    PhongTBL=NULL;
  54.    TextureMap=NULL;
  55.    LookPal=NULL;
  56.    LookPalPhong=NULL;
  57. }
  58.  
  59. VIDEOCLASS::~VIDEOCLASS(void)                // Destructor.
  60. {
  61.     if (pcx != NULL)
  62.     {
  63.       if (pcx->bitmap != NULL)
  64.         delete pcx->bitmap;
  65.       delete pcx;
  66.     }
  67.     if (VideoBuffer != NULL)
  68.       delete VideoBuffer;
  69.     if (Background != NULL)
  70.       delete Background;
  71.     if (TransTBL != NULL)
  72.       delete TransTBL;
  73.     if (PhongTBL != NULL)
  74.       delete PhongTBL;
  75.     if (HazeTBL != NULL)
  76.       delete HazeTBL;
  77.     if (TextureMap != NULL)
  78.       delete TextureMap;
  79.     if (LookPal != NULL)         // linear palette.
  80.       delete LookPal;
  81.     if (LookPalPhong != NULL)    // conforms to Phong illumination model.
  82.       delete LookPalPhong;      
  83.  
  84.     SetMode(prevmode);
  85. }
  86.  
  87. void VIDEOCLASS::InitVideo(int Mode)
  88. {   
  89.    prevmode = GetMode();  // get previous mode.
  90.  
  91.    switch (Mode)
  92.    {
  93.        case MCGA_320_200_256:
  94.          SetMode(0x13);
  95.  
  96.          _ScreenWidth = SCREENWIDTH = 320;
  97.          SCREENHEIGHT = 200;
  98.          SCREENSIZE = SCREENWIDTH*SCREENHEIGHT;
  99.          
  100.          HALF_SCREEN_WIDTH     = SCREENWIDTH/2;
  101.          HALF_SCREEN_HEIGHT    = SCREENHEIGHT/2;
  102.          ASPECT_SCREEN_HEIGHT  = 125;      // (6/5)*(200/2);
  103.          HALF_SCREEN_WIDTH_VD  = (float)HALF_SCREEN_WIDTH/(float)VIEWDISTANCE;
  104.          HALF_SCREEN_HEIGHT_VD = (float)ASPECT_SCREEN_HEIGHT/(float)VIEWDISTANCE;
  105.          SCANLINELENGTH        = (float)1/(float)SCREENWIDTH;
  106.  
  107.          _MinClipX = 10;
  108.          _MinClipY = 10;
  109.          _MaxClipX = 310;
  110.          _MaxClipY = 190;
  111.  
  112.          MEMSIZE=64000;
  113.        break;
  114.        
  115.        case SVGA_640_480_256:           // note: SVGA or mode other than 0x13
  116.          SetMode(0x101);                // hasn't been implemented yet. DOH!
  117.  
  118.          _ScreenWidth = SCREENWIDTH = 640;
  119.          SCREENHEIGHT = 480;
  120.          SCREENSIZE = SCREENWIDTH*SCREENHEIGHT;
  121.  
  122.          HALF_SCREEN_WIDTH     = SCREENWIDTH/2;
  123.          HALF_SCREEN_HEIGHT    = SCREENHEIGHT/2;
  124.          ASPECT_SCREEN_HEIGHT  = 240;      // no need to adjust by aspect ratio.
  125.          HALF_SCREEN_WIDTH_VD  =  (float)HALF_SCREEN_WIDTH/(float)VIEWDISTANCE;
  126.          HALF_SCREEN_HEIGHT_VD = (float)ASPECT_SCREEN_HEIGHT/(float)VIEWDISTANCE;
  127.          SCANLINELENGTH        = (float)1/(float)SCREENWIDTH;
  128.  
  129.          _MinClipX = 10;
  130.          _MinClipY = 10;
  131.          _MaxClipX = 630;
  132.          _MaxClipY = 470;
  133.  
  134.          MEMSIZE=307200;
  135.        break;
  136.        default:
  137.           Error("Couldn't find Video Mode\n");
  138.        break;
  139.    }
  140. }
  141.  
  142. void VIDEOCLASS::SetClipExtents(int XMinClip,int YMinClip,int XMaxClip,int YMaxClip,
  143.                                 int HitherClip,int YonClip)
  144. {
  145.    _MinClipX=XMinClip;
  146.    _MinClipY=YMinClip;
  147.    _MaxClipX=XMaxClip;
  148.    _MaxClipY=YMaxClip;
  149.     HITHER_Z=HitherClip;
  150.     YON_Z=YonClip;
  151. }                
  152.  
  153. unsigned char *VIDEOCLASS::LoadPcxFile(char *filename)
  154. {
  155.       unsigned long int i;
  156.       short int mode=NORMAL,nbytes;
  157.       unsigned char abyte,*p;
  158.       FILE *fptr;
  159.      
  160.       fptr=fopen(filename,"rb");
  161.       if (fptr==NULL)
  162.         Error("Couldn't Load PCX file\n");
  163.       
  164.       fread(&pcx->hdr,sizeof(PcxHeader),1,fptr);
  165.       pcx->width=(short int)(1+pcx->hdr.xmax-pcx->hdr.xmin);
  166.       pcx->height=(short int)(1+pcx->hdr.ymax-pcx->hdr.ymin);
  167.       pcx->imagebytes=pcx->width*pcx->height;
  168.       PcxSize = pcx->imagebytes;
  169.       if (pcx->bitmap != NULL)
  170.         delete pcx->bitmap;
  171.       pcx->bitmap=new unsigned char [ sizeof(char)*pcx->imagebytes ];
  172.       if (pcx->bitmap==NULL)
  173.         Error("Not enough memory\n");
  174.         
  175.       p=pcx->bitmap;
  176.       for(i=0;i<pcx->imagebytes;i++)
  177.       {
  178.         if(mode == NORMAL)
  179.         {
  180.           abyte=(unsigned char)fgetc(fptr);
  181.           if(( unsigned char )abyte > 0xbf)
  182.           {
  183.             nbytes=(short int)(abyte & 0x3f);
  184.             abyte=(unsigned char)fgetc(fptr);
  185.             if(--nbytes > 0)
  186.               mode=RLE;
  187.           }
  188.         }
  189.         else if(--nbytes == 0)
  190.           mode=NORMAL;
  191.         *p++=(unsigned char)abyte;
  192.       }
  193.  
  194.       fseek(fptr,-768L,SEEK_END);      // get palette from pcx file
  195.       fread(pcx->pal,768,1,fptr);
  196.       p=pcx->pal;
  197.       for(i=0;i<768;i++)            // bit shift palette
  198.         *p++=*p>>2;
  199.       fclose(fptr);
  200.  
  201.   return (pcx->bitmap);          // return pointer to bitmap.
  202. }
  203.  
  204. ImageStats *VIDEOCLASS::GetStats(void)
  205. {
  206.  
  207.    Stats.width = pcx->width;
  208.    Stats.height = pcx->height;
  209.    Stats.size = pcx->imagebytes;
  210.    
  211.    return (&Stats);
  212. }
  213.  
  214. void VIDEOCLASS::SetAllRgbPalette(void)     // Use pcx->palette.
  215. {
  216.   struct SREGS s;
  217.   union REGS r;
  218.  
  219.   memset(VidMem,0,MEMSIZE);             // clear VideoMemory (So nothing shows when palette is changed).
  220.   memcpy(CurrentPalette,pcx->pal,768);  // save current palette.
  221.  
  222.   segread(&s);                          // get current segment values
  223.   s.es=FP_SEG((void far*)pcx->pal);     // point ES to pal array
  224.   r.x.edx=FP_OFF((void far*)pcx->pal);  // get offset to pal array
  225.   r.x.eax=0x1012;                       // BIOS func 10h sub 12h
  226.   r.x.ebx=0;                            // starting DAC register
  227.   r.x.ecx=256;                          // ending DAC register
  228.   int386x(0x10,&r,&r,&s);               // call video BIOS
  229. }
  230.  
  231. void VIDEOCLASS::SetPaletteArg(unsigned char *pal)    // Set specific palette.
  232. {
  233.   struct SREGS s;
  234.   union REGS r;
  235.   
  236.   segread(&s);                          // get current segment values
  237.   s.es=FP_SEG((void far*)pal);          // point ES to pal array
  238.   r.x.edx=FP_OFF((void far*)pal);       // get offset to pal array
  239.   r.x.eax=0x1012;                       // BIOS func 10h sub 12h
  240.   r.x.ebx=0;                            // starting DAC register
  241.   r.x.ecx=256;                          // ending DAC register
  242.   int386x(0x10,&r,&r,&s);               // call video BIOS
  243. }
  244.  
  245. void VIDEOCLASS::CreateRGBPalette(void)
  246. {
  247.  int index; 
  248.  
  249.   for (index=0; index<64; index++)
  250.     {
  251.     outp(COLOR_REGISTER_WR, index);
  252.  
  253.     outp(COLOR_DATA,index);
  254.     outp(COLOR_DATA,index);
  255.     outp(COLOR_DATA,index);
  256.  
  257.     outp(COLOR_REGISTER_WR, index+64);
  258.  
  259.     outp(COLOR_DATA,index);
  260.     outp(COLOR_DATA,0);
  261.     outp(COLOR_DATA,0);
  262.     
  263.     outp(COLOR_REGISTER_WR, index+128);
  264.  
  265.     outp(COLOR_DATA,0);
  266.     outp(COLOR_DATA,index);
  267.     outp(COLOR_DATA,0);
  268.     
  269.     outp(COLOR_REGISTER_WR, index+192);
  270.  
  271.     outp(COLOR_DATA,0);
  272.     outp(COLOR_DATA,0);
  273.     outp(COLOR_DATA,index);    
  274.     } 
  275. }
  276.  
  277. void VIDEOCLASS::FadeToBlack(void)
  278. {
  279.  int index,index2; 
  280.  unsigned char Red,Green,Blue;
  281.  
  282.  for (index2=0; index2<30; index2++)     // probably good enough to cycle colors.
  283.  {
  284.    for (index=0; index<256; index++)
  285.    {
  286.      outp(COLOR_REGISTER_RD, index);
  287.  
  288.      Red=(unsigned char)inp(COLOR_DATA);
  289.      Green=(unsigned char)inp(COLOR_DATA);
  290.      Blue=(unsigned char)inp(COLOR_DATA);
  291.  
  292.      if (Red<5)
  293.        Red=0;
  294.      else
  295.       Red-=3;
  296.  
  297.      if (Green<5)
  298.        Green=0;
  299.      else
  300.        Green-=3;
  301.  
  302.      if (Blue<5)
  303.        Blue=0;
  304.      else
  305.        Blue-=3;
  306.         
  307.      outp(COLOR_REGISTER_WR, index);
  308.  
  309.      outp(COLOR_DATA,Red);
  310.      outp(COLOR_DATA,Green);
  311.      outp(COLOR_DATA,Blue);
  312.    }
  313.   WaitFor(1);
  314.  }
  315. }
  316.  
  317. void VIDEOCLASS::FadeToColor(void)
  318. {
  319.  int index,index2,colorindex; 
  320.  unsigned char Palette[768];
  321.  
  322.  memset(Palette,0,768);                  // make it black.
  323.  SetPaletteArg(Palette);
  324.  Buf2Video();                            // put to screen.
  325.  
  326.  for (index2=0; index2<30; index2++)     // probably good enough to cycle colors.
  327.  {
  328.    colorindex=0;  
  329.    for (index=0; index<256; index++)
  330.    {
  331.      outp(COLOR_REGISTER_WR, index);
  332.  
  333.      if ( Palette[colorindex] >= CurrentPalette[colorindex] )
  334.        Palette[colorindex]=CurrentPalette[colorindex];
  335.      else
  336.       Palette[colorindex]+=3;
  337.  
  338.      outp(COLOR_DATA,Palette[colorindex++]);
  339.  
  340.      if ( Palette[colorindex] >= CurrentPalette[colorindex] )
  341.        Palette[colorindex]=CurrentPalette[colorindex];
  342.      else
  343.       Palette[colorindex]+=3;
  344.  
  345.      outp(COLOR_DATA,Palette[colorindex++]);
  346.  
  347.      if ( Palette[colorindex] >= CurrentPalette[colorindex] )
  348.        Palette[colorindex]=CurrentPalette[colorindex];
  349.      else
  350.       Palette[colorindex]+=3;
  351.  
  352.      outp(COLOR_DATA,Palette[colorindex++]);
  353.    }
  354.   WaitFor(2);
  355.  }
  356. }
  357.  
  358. void VIDEOCLASS::LoadPalTable(char *filename)
  359. {
  360.  
  361.   FILE *fptr;
  362.   char tname[30],buffer[30];
  363.   unsigned char *texture;
  364.   
  365.   fptr=fopen(filename,"rb");
  366.   if (fptr==NULL)
  367.     Error("Couldn't Load Palette\n");
  368.  
  369.   fread((void *)buffer,sizeof(char),8,fptr);      // header.
  370.   fscanf(fptr,"%4d",&Shades);                     // num of shades.
  371.   
  372.   LookPal = new unsigned char [ sizeof(char)*Shades*256 ];      // allocate a giant lookup for palette.
  373.   if (LookPal==NULL)
  374.     Error("Not enough memory\n");
  375.     
  376.   fread((void *)buffer,sizeof(char),12,fptr);      // header.
  377.   fread((void *)buffer,sizeof(char),30,fptr);
  378.  
  379.   fread((void *)LookPal,sizeof(unsigned char),Shades*256,fptr);
  380.  
  381.   fclose(fptr);
  382.   
  383.   if (TextureMap == NULL)        // Texturemap not loaded, so use the texture, the palette was originally made from.
  384.   {
  385.       
  386.      strcpy(tname,"images/");           // prefix it with path.
  387.      strcat(tname,buffer);
  388.      texture=LoadPcxFile(tname);
  389.      SetAllRgbPalette();
  390.  
  391.      TextureMap  = new int [ sizeof(int)*PcxSize ];           // allocate Texture map.
  392.      if (TextureMap==NULL)
  393.        Error("Not enough memory\n");
  394.     
  395.      int index;
  396.  
  397.      for (index=0;index<PcxSize;index++)      // premultiply by num shades so i'll get correct offset in table.
  398.      {
  399.        TextureMap[index] = texture[index]*Shades;
  400.      }
  401.   }
  402.   
  403.  _LookPAL = LookPal;           // let polylow.asm have access to it.
  404. }
  405.  
  406. void VIDEOCLASS::LoadPalPhongTable(char *filename)
  407. {
  408.  
  409.   FILE *fptr;
  410.   char tname[30],buffer[30];
  411.   unsigned char *texture;
  412.  
  413.   // NOTE: with Phong illumination model applied to palette. Gouraud and
  414.   // Phong look very similar at a glance. But intensities for Gouraud are
  415.   // linear while intensity shading of Phong is not.
  416.  
  417.   fptr=fopen(filename,"rb");
  418.   if (fptr==NULL)
  419.     Error("Couldn't Load Palette\n");
  420.  
  421.   fread((void *)buffer,sizeof(char),8,fptr);      // header.
  422.   fscanf(fptr,"%4d",&Shades);                     // num of shades.
  423.   
  424.   LookPalPhong = new unsigned char [ sizeof(char)*Shades*256 ];      // allocate a giant lookup for palette.
  425.   if (LookPalPhong==NULL)
  426.     Error("Not enough memory\n");
  427.     
  428.   fread((void *)buffer,sizeof(char),12,fptr);      // header.
  429.   fread((void *)buffer,sizeof(char),30,fptr);
  430.  
  431.   fread((void *)LookPalPhong,sizeof(unsigned char),Shades*256,fptr);
  432.  
  433.   fclose(fptr);
  434.  
  435.   if (TextureMap == NULL)        // Texturemap not loaded, so use the texture, the palette was originally made from.
  436.   {
  437.       
  438.      strcpy(tname,"images/");           // prefix it with path.
  439.      strcat(tname,buffer);
  440.      texture=LoadPcxFile(tname);
  441.      SetAllRgbPalette();
  442.  
  443.      TextureMap  = new int [ sizeof(int)*PcxSize ];           // allocate Texture map.
  444.      if (TextureMap==NULL)
  445.        Error("Not enough memory\n");
  446.     
  447.      int index;
  448.  
  449.      for (index=0;index<PcxSize;index++)      // premultiply by num shades so i'll get correct offset in table.
  450.      {
  451.        TextureMap[index] = texture[index]*Shades;
  452.      }
  453.   }
  454. }  
  455.  
  456. void VIDEOCLASS::LoadTextureMap(char *filename)
  457. {
  458.   unsigned char *texture;
  459.  
  460.      texture=LoadPcxFile(filename);
  461.      SetAllRgbPalette();
  462.  
  463.      TextureMap  = new int [ sizeof(int)*PcxSize ];           // allocate Texture map.
  464.      if (TextureMap==NULL)
  465.        Error("Not enough memory\n");
  466.     
  467.      int index;
  468.  
  469.      for (index=0;index<PcxSize;index++)      // premultiply by num shades so i'll get correct offset in table.
  470.      {
  471.        TextureMap[index] = texture[index]*64;  // default to 64 shades.
  472.      }
  473. }
  474.     
  475. int VIDEOCLASS::LoadTransTable(char *filename)
  476. {
  477.   FILE *fptr;
  478.   char tname[30],buffer[30];
  479.   int numread, Levels;
  480.   
  481.   fptr=fopen(filename,"rb");
  482.   if (fptr==NULL)
  483.    Error("Unable to Load Transparency Table\n");
  484.    
  485.   numread=fread((void *)buffer,sizeof(char),19,fptr);    // header.
  486.   numread=fscanf(fptr,"%2d",&Levels);
  487.  
  488.   TransTBL = new unsigned char [ sizeof(char)*256*256*Levels ];      // allocate a giant trans lookup.
  489.   if (TransTBL==NULL)
  490.     Error("Not enough memory\n");
  491.     
  492.   numread=fread((void *)buffer,sizeof(char),12,fptr);    // header.
  493.   numread=fread((void *)tname,sizeof(char),30,fptr);  
  494.   numread=fread((void *)TransTBL,sizeof(unsigned char),256*256*Levels,fptr);    // load in table.
  495.  
  496.   fclose(fptr);
  497.   
  498.   return (Levels-1);   // we don't want fully transparent.
  499. }
  500.  
  501. void VIDEOCLASS::LoadHazeTable(char *filename)
  502. {
  503.   FILE *fptr;
  504.   char buffer[30];
  505.   char texture[30];
  506.   int Levels;
  507.     
  508.   fptr=fopen(filename,"rb");
  509.   
  510.   fread((void *)buffer,sizeof(char),11,fptr);    // header.
  511.   fscanf(fptr,"%4d",&Levels);
  512.  
  513.   HazeTBL = new unsigned char [ sizeof(char)*256*Levels ];      // allocate a giant haze lookup.
  514.   if (HazeTBL==NULL)
  515.     Error("Not enough memory\n");
  516.     
  517.   fread((void *)buffer,sizeof(char),12,fptr);    // header.
  518.   fread((void *)texture,sizeof(char),30,fptr);
  519.   fread((void *)HazeTBL,sizeof(unsigned char),256*Levels,fptr);    // load in table.
  520.     
  521.   fclose(fptr);
  522. }  
  523.  
  524. void VIDEOCLASS::LoadPhongTBL(char *filename)  // holds precomputed angles.
  525. {
  526.   FILE *fptr;
  527.   char buffer[30];
  528.  
  529.   PhongTBL = new int [ sizeof(int)*90*256 ];  // for 90 degrees in fixed point 8.
  530.   if (PhongTBL==NULL)
  531.     Error("Not enough memory\n");    
  532.  
  533.   fptr=fopen(filename,"rb");
  534.   if (fptr==NULL)
  535.     Error("Couldn't load PHONG table\n");
  536.  
  537.   fread((void *)buffer,sizeof(char),13,fptr);   // header.
  538.   fread((void *)PhongTBL,sizeof(int),90*256,fptr);    // load in table.
  539.  
  540.   fclose(fptr);
  541. }
  542.  
  543. unsigned char *VIDEOCLASS::CreateBuffer(int color)
  544. {
  545.    VideoBuffer = new unsigned char[ sizeof(char)*MEMSIZE ];     // we know how big, by what video mode we're in.
  546. //VideoBuffer=(unsigned char *)0xa0000;        // for Debug purposes. Set if want ouput directly to screen. ( Rem the line above first. )
  547.  
  548.    if (VideoBuffer==NULL)
  549.      Error("not enough memory for VideoBuffer\n");
  550.  
  551.   bgcolor=color;                                // color to clear buffer with.
  552.  
  553.   _RendBuffer=VideoBuffer;                      // let polylow.asm have access to buffer.
  554.   return (VideoBuffer);
  555. }
  556.  
  557. void VIDEOCLASS::ClearBuffer(void)
  558.    if (Background != NULL)               // if there is a background loaded, use it.
  559.      memcpy(VideoBuffer,Background,MEMSIZE);
  560.    else 
  561.      memset(VideoBuffer,bgcolor,MEMSIZE);
  562. }
  563.  
  564. void VIDEOCLASS::Buf2Video(void)
  565. {
  566.    ZapBuff(VidMem,VideoBuffer,MEMSIZE>>2);   // dwords at a time.
  567. }
  568.  
  569. void VIDEOCLASS::LoadBackground(char *filename)
  570. {
  571.    
  572.    if (Background != NULL)
  573.      delete Background;
  574.  
  575.    Background = new unsigned char [ sizeof(char)*MEMSIZE ];
  576.    if (Background==NULL)
  577.      Error("not enough memory\n");
  578.  
  579.    unsigned char *bitmap;
  580.    bitmap=LoadPcxFile(filename);
  581.  
  582.    memcpy(Background,bitmap,MEMSIZE);
  583.    memcpy(VideoBuffer,Background,MEMSIZE);    
  584. }
  585.  
  586. void VIDEOCLASS::DeleteBackground(void)
  587. {
  588.   if (Background != NULL)
  589.   {
  590.     delete Background;
  591.     Background=NULL;
  592.   }
  593. }
  594.  
  595. unsigned char *VIDEOCLASS::GetBuffer(void)
  596. {
  597.    return (VideoBuffer);
  598. }
  599.  
  600.